package org.jeecg.modules.compilation.util;


import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Slf4j
public class PdfUtils {

    /**
     * pdf加密
     *
     * @param filePath  输入文件路径
     * @param savePath  输出文件路径
     * @param password  密码
     * @return
     */
    public static boolean pdfEncrypt(String filePath, String savePath, String password){
        try{
            PdfReader reader = new PdfReader(filePath);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(savePath));

            //ALLOW_PRINTING	文档允许打印
            //ALLOW_DEGRADED_PRINTING	允许用户打印文档，但不提供allow_printing质量（128位加密）
            //ALLOW_MODIFY_CONTENTS	允许用户修改内容，例如 更改页面内容，或插入或删除页
            //ALLOW_ASSEMBLY	允许用户插入、删除和旋转页面和添加书签。页面的内容不能更改，除非也授予allow_modify_contents权限，（128位加密）
            //ALLOW_COPY	允许用户复制或以其他方式从文档中提取文本和图形，包括使用辅助技术。例如屏幕阅读器或其他可访问设备
            //ALLOW_SCREENREADERS	允许用户提取文本和图形以供易访问性设备使用，（128位加密）
            //ALLOW_MODIFY_ANNOTATIONS	允许用户添加或修改文本注释和交互式表单字段
            //ALLOW_FILL_IN	允许用户填写表单字段，（128位加密）

            //访问者密码，拥有者密码(权限密码让pdf文件无法被修改)，访问者权限，加密方式。
            stamper.setEncryption(null, password.getBytes(),PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_DEGRADED_PRINTING,PdfWriter.STANDARD_ENCRYPTION_128);
            stamper.close();
            reader.close();
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    public static Integer getPdfNum(String inputFile){
        log.info("pdf文件存储地址：{}",inputFile);
        PdfReader reader = null;
        try {
            reader = new PdfReader(inputFile);
            log.info("pdf页数：{}",reader.getNumberOfPages() + 1);
            return reader.getNumberOfPages() + 1;
        }catch (Exception e){
            log.info(e.getMessage());
        }
        return 0;
    }

    /**
     * pdf添加水印
     *
     * @param inputFile     需要添加水印的文件
     * @param outputFile    添加完水印的文件存放路径
     * @param opacity       水印字体透明度
     * @param fontsize      水印字体大小
     * @param angle         水印倾斜角度（0-360）
     * @param heightdensity 数值越大每页竖向水印越少
     * @param widthdensity  数值越大每页横向水印越少
     * @param cover         是否覆盖
     * @return
     */
    public  static boolean addwaterMark(
            String text, String inputFile, String outputFile,
                                       float opacity, int fontsize, int angle, int heightdensity, int widthdensity, boolean cover) {
        if (!cover) {
            File file = new File(outputFile);
            if (file.exists()) {
                return true;
            }
        }
        File file = new File(inputFile);
        if (!file.exists()) {
            return false;
        }

        PdfReader reader = null;
        PdfStamper stamper = null;
        try {
            int interval = -5;
            reader = new PdfReader(inputFile);
            stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
            Rectangle pageRect = null;
            PdfGState gs = new PdfGState();
            //这里是透明度设置
            gs.setFillOpacity(opacity);
            //这里是条纹不透明度
            gs.setStrokeOpacity(0.2f);
            int total = reader.getNumberOfPages() + 1;
            log.info("Pdf页数：{}", reader.getNumberOfPages());
            JLabel label = new JLabel();
            FontMetrics metrics;
            int textH = 0;
            int textW = 0;
            label.setText("text");
            metrics = label.getFontMetrics(label.getFont());
            //字符串的高,   只和字体有关
            textH = metrics.getHeight();
            //字符串的宽
            textW = metrics.stringWidth(label.getText());
            PdfContentByte under;
            //这个循环是确保每一张PDF都加上水印
            for (int i = 1; i < total; i++) {
                pageRect = reader.getPageSizeWithRotation(i);
                under = stamper.getOverContent(i);  //在内容上方添加水印
//                under = stamper.getUnderContent(i);  //在内容下方添加水印
                under.saveState();
                under.setGState(gs);
                under.beginText();
                //under.setColorFill(BaseColor.PINK);  //添加文字颜色  不能动态改变 放弃使用
                under.setFontAndSize(base, fontsize); //这里是水印字体大小
//                for (int height = textH; height < pageRect.getHeight() * 2; height = height + textH * heightdensity) {
//                    for (int width = textW; width < pageRect.getWidth() * 1.5 + textW; width = width + textW * widthdensity) {
//                        // rotation:倾斜角度
//                        under.showTextAligned(Element.ALIGN_LEFT, "测试水印测试水印", width - textW, height - textH, angle);
//                    }
//                }
                Font waterMarkFont = new Font(base, fontsize);
                Phrase phrase = new Phrase(text, waterMarkFont);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.10f, pageRect.getHeight()*0.2f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.10f, pageRect.getHeight()*0.5f,45);
                ColumnText.showTextAligned(under, Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.10f, pageRect.getHeight()*0.8f,45);

                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.250f, pageRect.getHeight()*0.2f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.250f, pageRect.getHeight()*0.5f,45);
                ColumnText.showTextAligned(under, Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.250f, pageRect.getHeight()*0.8f,45);

                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.40f, pageRect.getHeight()*0.2f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.40f, pageRect.getHeight()*0.5f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.40f, pageRect.getHeight()*0.8f,45);

                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.55f, pageRect.getHeight()*0.2f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.55f, pageRect.getHeight()*0.5f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.55f, pageRect.getHeight()*0.8f,45);

                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.70f, pageRect.getHeight()*0.2f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.70f, pageRect.getHeight()*0.5f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.70f, pageRect.getHeight()*0.8f,45);

                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.85f, pageRect.getHeight()*0.2f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.85f, pageRect.getHeight()*0.5f,45);
                ColumnText.showTextAligned(under,Element.ALIGN_CENTER,phrase,
                        pageRect.getWidth()*0.85f, pageRect.getHeight()*0.8f,45);


                //添加水印文字
                under.endText();
            }
            log.info("添加水印成功！");
            return true;
        } catch (IOException e) {
            log.info("添加水印失败！错误信息为: " + e);
            e.printStackTrace();
            return false;
        } catch (DocumentException e) {
            System.out.println("添加水印失败！错误信息为: " + e);
            e.printStackTrace();
            return false;
        } finally {
            //关闭流
            if (stamper != null) {
                try {
                    stamper.close();
                } catch (DocumentException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                reader.close();
            }
        }
    }

    public static File mergeFiles(String[] files, String result, boolean smart) throws IOException, DocumentException {
        Document document = new Document();
        PdfCopy copy;
        if (smart)
            copy = new PdfSmartCopy(document, new FileOutputStream(result));
        else
            copy = new PdfCopy(document, new FileOutputStream(result));
        document.open();
        PdfReader[] reader = new PdfReader[files.length];
        for (int i = 0; i < files.length; i++) {
            reader[i] = new PdfReader(files[i]);
            copy.addDocument(reader[i]);
            copy.freeReader(reader[i]);
            reader[i].close();
        }
        document.close();
        return new File(result);
    }

    /**
     * 合并pdf
     *
     * @param streamOfPDFFiles
     * @param outputStream
     * @param paginate
     */
    public static void concatPDFs(List<InputStream> streamOfPDFFiles,
                                  OutputStream outputStream, boolean paginate) {

        Document document = new Document();
        try {
            List<InputStream> pdfs = streamOfPDFFiles;
            List<PdfReader> readers = new ArrayList<PdfReader>();
            int totalPages = 0;
            Iterator<InputStream> iteratorPDFs = pdfs.iterator();

            // Create Readers for the pdfs.
            while (iteratorPDFs.hasNext()) {
                InputStream pdf = iteratorPDFs.next();
                PdfReader pdfReader = new PdfReader(pdf);
                readers.add(pdfReader);
                totalPages += pdfReader.getNumberOfPages();
            }
            // Create a writer for the outputstream
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);

            document.open();
            BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
                    BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
            PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
            // data

            PdfImportedPage page;
            int currentPageNumber = 0;
            int pageOfCurrentReaderPDF = 0;
            Iterator<PdfReader> iteratorPDFReader = readers.iterator();

            // Loop through the PDF files and add to the output.
            while (iteratorPDFReader.hasNext()) {
                PdfReader pdfReader = iteratorPDFReader.next();

                // Create a new page in the target for each source page.
                while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
                    document.newPage();
                    pageOfCurrentReaderPDF++;
                    currentPageNumber++;
                    page = writer.getImportedPage(pdfReader,
                            pageOfCurrentReaderPDF);
                    cb.addTemplate(page, 0, 0);

                    // Code for pagination.
                    if (paginate) {
                        cb.beginText();
                        cb.setFontAndSize(bf, 9);
                        cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
                                        + currentPageNumber + " of " + totalPages, 520,
                                5, 0);
                        cb.endText();
                    }
                }
                pageOfCurrentReaderPDF = 0;
            }
            outputStream.flush();
            document.close();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (document.isOpen())
                document.close();
            try {
                if (outputStream != null)
                    outputStream.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    /**
     * <br>
     * <p>
     * Description: 给pdf文件添加水印 <br>
     * <p><br/>
     * <p>
     *
     * @param InPdfFile     要加水印的原pdf文件路径
     * @param outPdfFile    加了水印后要输出的路径
     * @param markImagePath 水印图片路径
     * @param imgWidth      图片横坐标
     * @param imgHeight     图片纵坐标
     * @throws Exception
     */
    public static void addPdfImgMark(String InPdfFile, String outPdfFile, String markImagePath, int imgWidth, int imgHeight) throws Exception {
        PdfReader reader = new PdfReader(InPdfFile, "PDF".getBytes());
        PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(new File(outPdfFile)));

        PdfContentByte under;

        PdfGState gs1 = new PdfGState();
        gs1.setFillOpacity(0.5f);// 透明度设置

        com.itextpdf.text.Image img = Image.getInstance(markImagePath);// 插入图片水印

        img.setAbsolutePosition(imgWidth, imgHeight); // 坐标
//        img.setRotation(-20);// 旋转 弧度
//        img.setRotationDegrees(45);// 旋转 角度
        // img.scaleAbsolute(200,100);//自定义大小
        // img.scalePercent(50);//依照比例缩放

        int pageSize = reader.getNumberOfPages();// 原pdf文件的总页数
        for (int i = 1; i <= pageSize; i++) {
            under = stamp.getUnderContent(i);// 水印在之前文本下
            // under = stamp.getOverContent(i);//水印在之前文本上
            under.setGState(gs1);// 图片水印 透明度
            under.addImage(img);// 图片水印
        }

        stamp.close();// 关闭
        // // 删除不带水印文件
//		File tempfile = new File(InPdfFile);
//		if(tempfile.exists()) {
//			tempfile.delete();
//		}

    }

    /**
     * <br>
     * <p>
     * Description: 给pdf文件添加水印<br>
     *
     * @param InPdfFile  要加水印的原pdf文件路径
     * @param outPdfFile 加了水印后要输出的路径
     * @param textMark   水印文字
     * @param textWidth  文字横坐标
     * @param textHeight 文字纵坐标
     * @throws Exception
     */
    public static void addPdfTextMark(String InPdfFile, String outPdfFile, String textMark, int textWidth,
                                      int textHeight) throws Exception {
        PdfReader reader = new PdfReader(InPdfFile, "PDF".getBytes());
        PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(new File(outPdfFile)));

        PdfContentByte under;

        BaseFont font = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1", "Identity-H", true);// 使用系统字体

        int pageSize = reader.getNumberOfPages();// 原pdf文件的总页数
        for (int i = 1; i <= pageSize; i++) {
            under = stamp.getUnderContent(i);// 水印在之前文本下
            // under = stamp.getOverContent(i);//水印在之前文本上
            under.beginText();
            under.setColorFill(BaseColor.GRAY);// 文字水印 颜色
            under.setFontAndSize(font, 38);// 文字水印 字体及字号
            under.setTextMatrix(textWidth, textHeight);// 文字水印 起始位置
            under.showTextAligned(Element.ALIGN_CENTER, textMark, textWidth, textHeight, 45);
            under.endText();
        }

        stamp.close();// 关闭
    }

//    public static void main(String [] str) {
//        System.out.println( getPdfNum("D:\\中烟办〔2020〕43号.pdf"));
//    }

}